<?php

namespace app\api\controller\qixing;

use app\common\controller\Api;
use app\common\library\Ems;
use app\common\library\Sms;
use app\common\library\Upload;
use fast\Random;
use fast\Http;
use think\Request;
use think\Config;
use think\Validate;
use think\Db;
use addons\kefu\library\Common;
use addons\kefu\library\Captcha;
use app\api\model\Tryride;

/**
 * 骑行接口
 */
class Cycling extends Api
{
    protected $noNeedLogin = ['test','crawler'];
    protected $noNeedRight = '*';

    public function _initialize()
    {
        parent::_initialize();
        define('PI',3.1415926535898);
        define('EARTH_RADIUS',6378.137);
        //英里公式 mi = m * 0.00062137
    }

    /**
     * 骑行记录 筛选条件
     */
    public function list()
    {
        $userid = $this->auth->id;
        $params = $this->request->post();
        $page = isset($params['page'])&&is_numeric($params['page']) ? $params['page'] : 1;
        $pageSize = isset($params['pageSize'])&&is_numeric($params['pageSize']) ? $params['pageSize'] : 10;
        $where = [];
        $wheretime = '';
        if (isset($params['address'])) {
            $where['user_post'] = ['like','%'.$params['address'].'%'];
            $where['end_post'] = ['like','%'.$params['address'].'%'];
        }
        // if (isset($params['day'])&&$params['day']!='') {
        //     $wheretime['createtime'] = $params['day'];
        // }
        if (isset($params['time'])&&$params['time']!='') {
            $where['createtime'] = ['like','%'.$params['time'].'%'];
        }
        $where['userid'] = $userid;
        $where['actualdistance'] = ['>',161];

        //当日里程
        $mileage = Db::name('cycling')->where('userid',$userid)->whereTime('createtime', 'today')->sum('actualdistance');
        //$mileage = $mileage>=100?floatval(sprintf('%.1f',$mileage/1000)).'km':floatval($mileage).'m';
        $mileage = $mileage>=10?floatval(sprintf('%.1f',$mileage * 0.00062137)).'miles':'0.0miles';
        //当日时长
        $actualDuration = Db::name('cycling')->where('userid',$userid)->whereTime('createtime', 'today')->sum('actualDuration');
        $timelength = $actualDuration>0?$this->changeTimeType($actualDuration):'00:00:00';
        //当日爬坡
        $num = Db::name('cycling')->where('userid',$userid)->where('climb','>',0)->whereTime('createtime', 'today')->sum('climb');
        //当日卡路里
        $calories = Db::name('cycling')->where('userid',$userid)->whereTime('createtime', 'today')->sum('calories');
        $today = [
            'mileage' => $mileage,
            'timelength' => $timelength,
            'num' => $num?floatval(sprintf('%.1f',$num*3.28083989501)).'feet':'0feet',
            'calories' => $calories.'kcal'
        ];
        $list = Db::name('cycling')
                ->where($where)
                // ->whereTime($wheretime)
                ->order('createtime desc')
                ->limit(($page - 1)*$pageSize,$pageSize)
                ->select();
        foreach ($list as &$vs) {
            $vs['startdate'] = date_format(date_create($vs['createtime']),'Y.m.d');
            $end = $vs['endtime']?date_format(date_create($vs['endtime']),'H:i:s'):'?';
            $vs['stend'] = date_format(date_create($vs['createtime']),'H:i:s').'~'.$end;
            //$vs['mileage'] = $vs['actualdistance']>=100?floatval(sprintf('%.1f',$vs['actualdistance']/1000)).'km':floatval($vs['actualdistance']).'m';
            $vs['mileage'] = $vs['actualdistance']>100?floatval(sprintf('%.1f',$vs['actualdistance'] * 0.00062137)).'miles':'0.0miles';
            $vs['timelength'] = $vs['actualDuration']>0?$this->changeTimeType($vs['actualDuration']):'00:00:00';
            $vs['num'] = floatval(sprintf('%.1f',$vs['climb']*3.28083989501)).'feet';
            $vs['calories'] = $vs['calories'].'kcal';
        }
        unset($vs);
        $data = [
                    'today' => $today,
                    'list'  => $list
                ];
        $this->success('', $data);
    }


    /**
     * 开始骑行
     */
    public function start()
    {
        $userid = $this->auth->id;
        $this->fangchu();
        $params = $this->request->post();
        $checkarr = ['equipmentid','user_lng','user_lat'];
        $check  = array_intersect($checkarr,array_keys($params));
        if (count($check) != count($checkarr)) {
            $this->error(__('Invalid parameters'));
        }
        if ($params['user_lng']&&$params['user_lat']) {
            $postplace = $this->mapboxaddress($params['user_lng'].",".$params['user_lat']);
            $params['user_post'] = $postplace['post'];
            $params['user_region'] = $postplace['place'];
        }
        // if (isset($params['end_lng'])&&isset($params['end_lat'])&&$params['end_lng']&&$params['end_lat']) {
        //     $postplace = $this->mapboxaddress($params['end_lng'].",".$params['end_lat']);
        //     $params['end_post'] = $postplace['post'];
        // }
        $params['userid'] = $userid;
        $params['state'] = 1;
        //记录用户骑行位置
        Db::name('user')->where(['id'=>$userid])->update(['lng'=>$params['user_lng'],'lat'=>$params['user_lat']]);
        $params['createtime'] = date('Y-m-d H:i:s',time());
        $cid = Db::name('cycling')->insertGetId($params);
        Db::name('user')->where('id',$userid)->update(['cyclingStatus'=>1]);
        $data = [
                    'cid'  => $cid
                ];
        $this->success(__('Started riding'),$data);
    }

    /**
     * 骑行暂停及结束
     */
    public function suspendend()
    {
        $userid = $this->auth->id;
        $user = $this->auth->getUser();
        $cid = $this->request->post('cid');
        $state = $this->request->post('state');
        $actualdistance = $this->request->post('actualdistance');
        $duration = $this->request->post('duration');
        $end_post = $this->request->post('end_post');
        $end_lng = $this->request->post('end_lng');
        $end_lat = $this->request->post('end_lat');
        $file = $this->request->post('file');
        if (!$cid||!$state) {
            $this->error(__('Invalid parameters'));
        }
        $qix = Db::name('cycling')->where(['id'=>$cid,'state'=>['in','1,2']])->find();
        if (!$qix) {
            $this->error(__('Cycling is over'));
        }
        $data = [];
        $data['state'] = $state;
        if ($actualdistance) {
            $data['actualdistance'] = $actualdistance;
        }
        if ($duration) {
            $data['actualDuration'] = $duration;
        }
        if ($state==3) {
            $ridi = json_decode(Db::name('user_riding_heartbeat')->where(['cid'=>$cid,'uid'=>$userid])->value('jsonlist'),true);
            if (!$ridi) {
                $this->error(__('The end of the ride too fast'));
            }
            if (!$duration) {
                $startTime = strtotime(Db::name('cycling')->where('id',$cid)->value('createtime'));
                $data['actualDuration'] = time()-$startTime;
            }

            if($file){
                $data['lineimg'] = $file;
            }
            
            
            //获取累积高度
            if (isset($ridi[count($ridi)-1]['totalalt'])) {
                $data['climb'] = floatval($ridi[count($ridi)-1]['totalalt']);
            }
            
            

            if (!$actualdistance) {
                $data['actualdistance'] = floatval(sprintf('%.1f',$ridi[count($ridi)-1]['distance']));
            }
            
            //计算卡路里 代谢当量*时间（小时）*体重（公斤）*1.05（系数）
            if (!$user['weight']) {
                //未设置体重给一个默认体重
                $user['weight'] = 65;
            }
            $ctime = time()-strtotime(Db::name('cycling')->where(['id'=>$cid])->value('createtime'));
            $data['calories'] = floatval(sprintf('%.1f',6.5*($ctime/3600)*$user['weight']*1.05));

            if ($end_post) {
                $data['end_post'] = $end_post;
            }
            if ($end_lng) {
                $data['end_lng'] = $end_lng;
            }
            if ($end_lat) {
                $data['end_lat'] = $end_lat;
            }
            
            if ($end_lng&&$end_lat) {
                $postplace = $this->mapboxaddress($end_lng.",".$end_lat);
                $data['end_post'] = $postplace['post'];
            }
            //记录用户位置
            Db::name('user')->where(['id'=>$userid])->update(['lng'=>$end_lng,'lat'=>$end_lat]);
            //记录用户骑行里程
            $totaldistance = Db::name('user_cycling')->where(['uid'=>$userid])->find();
            if ($totaldistance) {
                Db::name('user_cycling')->where(['uid'=>$userid])->setInc('totaldistance',$data['actualdistance']);
            }else{
                Db::name('user_cycling')->insert(['uid'=>$userid,'totaldistance'=>$data['actualdistance'],'createtime'=>date('Y-m-d H:i:s',time())]);
            }
            //获取勋章等级并更新
            $totaldistance = Db::name('user_cycling')->where(['uid'=>$userid])->value('totaldistance');
            $levelid = Db::name('user_level')->where(['totaldistance'=>['<=',floatval(sprintf('%.1f',$totaldistance* 0.00062137))]])->order('totaldistance desc')->value('id');
            Db::name('user')->where(['id'=>$userid])->update(['level'=>$levelid]);
            
            $data['endtime'] = date('Y-m-d H:i:s',time());   
        }
        Db::name('cycling')->where('id',$cid)->update($data);
        Db::name('user')->where('id',$userid)->update(['cyclingStatus'=>0]);
        if($state==1){
            $this->success(__('Ride to continue'));
        }elseif($state==2){
            $this->success(__('Ride to suspend'));
        }else{
            $this->success(__('End of the cycling'));
        }
        
    }
    //mapbox反向地理解析
    function mapboxaddress($latlng){
        $token = 'pk.eyJ1IjoibGFuZ2RvbmdsZWkiLCJhIjoiY2xmOWRvcjg1MmV2bDNybGh3dWs5eDNhaCJ9.ILQRw5E7y-vRdykulCTe6w';
        $result = Http::sendRequest("https://api.mapbox.com/geocoding/v5/mapbox.places/".$latlng.".json?types=country,region,place,address&access_token=".$token, [], 'GET');
        $data = [];
        if ($result['ret']) {
            $da = (array)json_decode($result['msg'], true);
            if ($da['features']&&count($da['features'])==4) {
                foreach ($da['features'] as $vv) {
                    if ($vv['place_type'][0]=='address') {
                        $data['post'] = $vv['place_name'];
                    }
                    if ($vv['place_type'][0]=='place') {
                        $data['place'] = $vv['place_name'];
                    }
                }
            }else{
                //高德地图解析
                $data = $this->gaodeaddress($latlng);
            }
        }else{
            //高德地图解析
            $data = $this->gaodeaddress($latlng);
        }
        return $data;
    }
    //高德反向地理解析
    function gaodeaddress($latlng){
        $result = Http::sendRequest("https://restapi.amap.com/v3/geocode/regeo?output=json&location=".$latlng."&key=5e0d711dc520a746549847425fc5465f&radius=1000&extensions=base&batch=false", [], 'GET');
        $data = [];
        if ($result['ret']) {
            $da = (array)json_decode($result['msg'], true);
            if (isset($da['regeocode']['formatted_address'])) {
                $data['post'] = $da['regeocode']['formatted_address'];
                $country = $da['regeocode']['addressComponent']['country']?$da['regeocode']['addressComponent']['country']:'';
                $province = $da['regeocode']['addressComponent']['province']?','.$da['regeocode']['addressComponent']['province']:'';
                $city = $da['regeocode']['addressComponent']['city']?','.$da['regeocode']['addressComponent']['city']:'';
                $data['place'] = $country.$province.$city;
            }else{
                $data['post'] = 'Unknown location';
                $data['place'] = 'Unknown';
            }
        
        }else{
            $data['post'] = 'Unknown location';
            $data['place'] = 'Unknown';
        }
        return $data;
    }

    /**
     * 骑行线路详情
     */
    public function cyclingDetail()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        $detail = Db::name('cycling')
        ->where(['id'=>$id])
        ->find();
        if ($detail) {
            $ridi = json_decode(Db::name('user_riding_heartbeat')->where(['cid'=>$id])->value('jsonlist'),true);
            $detail['json'] = $ridi;
            //$detail['lineimg'] = cdnurl($detail['lineimg'],true);
            $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
            $detail['fulllineimg'] = '';
            if(!preg_match($str, $detail['lineimg']))
            { 
                $detail['fulllineimg'] = cdnurl($detail['lineimg'],true);
            }else{
                $detail['fulllineimg'] = $detail['lineimg'];
            }
            $detail['start'] = strtotime($detail['createtime']);
            $detail['end'] = strtotime($detail['endtime']);
            $detail['startdate'] = date_format(date_create($detail['createtime']),'Y.m.d');
            $end = $detail['endtime']?date_format(date_create($detail['endtime']),'H:i:s'):'?';
            $detail['stend'] = date_format(date_create($detail['createtime']),'H:i:s').'~'.$end;
            //$detail['mileage'] = $detail['actualdistance']>100 ? floatval(sprintf('%.1f',$detail['actualdistance']/1000)).'km':floatval($detail['actualdistance']).'m';
            $detail['mileage'] = $detail['actualdistance']>=60?floatval(sprintf('%.1f',$detail['actualdistance'] * 0.00062137)).'miles':'0.0miles';
            $detail['timelength'] = $detail['actualDuration']>0?$this->changeTimeType($detail['actualDuration']):'00:00:00';
            $detail['num'] = floatval(sprintf('%.1f',$detail['climb']*3.28083989501)).'feet';
            $detail['calories'] = $detail['calories'].'kcal';
            $x = [];//x轴骑行距离组
            $alt = [];//高度组
            $speed = [];//速度组
            $minutes = [];//分钟组
            $heart = [];//心率组
            $zuialt = 0;//最高爬升
            $zuifall = 0;//最低爬升
            $totalperhour = 0;//全程均速
            $perhour = 0;//最快速度
            $totalalt = 0;//累计爬升
            $totalfalling = 0;//累计下降
            if ($ridi) {
                //累计爬升
                $totalalt = isset($ridi[count($ridi)-1]['totalalt'])?$ridi[count($ridi)-1]['totalalt']:0;
                //$totalalt = $totalalt>=1000?floatval(sprintf('%.1f',$totalalt/1000)).'km':floatval(sprintf('%.1f',$totalalt)).'m';
                $totalalt = floatval(sprintf('%.1f',$totalalt*3.28083989501)).'feet';
                //$totalalt = $totalalt>=100?floatval(sprintf('%.1f',$totalalt * 0.00062137)).'mi':floatval($totalalt).'m';
                //累计下降
                $totalfalling = isset($ridi[count($ridi)-1]['totalfalling'])?$ridi[count($ridi)-1]['totalfalling']:0;
                //$totalfalling = $totalfalling>=1000?floatval(sprintf('%.1f',$totalfalling/1000)).'km':floatval(sprintf('%.1f',$totalfalling)).'m';
                $totalfalling = floatval(sprintf('%.1f',$totalfalling*3.28083989501)).'feet';
                //全程均速
                if (isset($ridi[count($ridi)-1]['totime'])) {
                        $totime = $ridi[count($ridi)-1]['totime']>0?floatval(sprintf('%.1f',$ridi[count($ridi)-1]['totime']/3600)):0;
                        $dis = $ridi[count($ridi)-1]['distance']>0?floatval(sprintf('%.1f',$ridi[count($ridi)-1]['distance']*0.00062137)):0;
                        if ($dis>0&&$totime>0) {
                            $totalperhour = floatval(sprintf('%.1f',$dis/$totime)); 
                            
                        }else{
                            $totalperhour = 0;
                        }
                        
                }
                
               $n = count($ridi)>=7?intval(count($ridi)/6):1;
                $s = $n==1?count($ridi):7;
                $t = 0;
                for ($i=0; $i < $s; $i++) { 
                    if ($i==6) {
                        $t = count($ridi)-1;
                    }
                    if (isset($ridi[$t]['distance'])) {
                        $x[$i] = $ridi[$t]['distance']>0?floatval(sprintf('%.1f',$ridi[$t]['distance']/1000)):0;
                    }
                    if (isset($ridi[$t]['totalalt'])) {
                        $alt[$i] = $ridi[$t]['totalalt']>0?floatval(sprintf('%.0f',$ridi[$t]['totalalt']*3.28083989501)):0;
                        if ($alt[$i]>$zuialt) {
                            $zuialt = $alt[$i];
                        }else{
                            $zuifall = $alt[$i];
                        }
                    }else{
                        $alt[$i] = 0;
                    }
                    if (isset($ridi[$t]['totime'])) {
                        $totime = $ridi[$t]['totime']>0?floatval(sprintf('%.4f',$ridi[$t]['totime']/3600)):0;
                        //$dis = $ridi[$t]['distance']>0?floatval(sprintf('%.4f',$ridi[$t]['distance']/1000)):0;
                        $dis = $ridi[$t]['distance']>0?floatval(sprintf('%.4f',$ridi[$t]['distance']*0.00062137)):0;
                        if ($dis==0||$totime==0) {
                            $speed[$i] = 0;
                        }else{
                            $speed[$i] = floatval(sprintf('%.1f',$dis/$totime));
                        }
                        
                        if ($speed[$i]>$perhour) {
                            $perhour = $speed[$i];
                        }
                    }
                    if (isset($ridi[$t]['heartrate'])) {
                        $minutes[$i] = $ridi[$t]['totime']>=60?intval(sprintf('%.1f',$ridi[$t]['totime']/60)):1;
                        $heart[$i] = floatval($ridi[$t]['heartrate']);
                    }else{
                        $minutes[$i] = 0;
                        $heart[$i] = 0;
                    }

                    $t = $t+$n;
                    
                }
            }
            $detail['highly'] = [
                'x' => $x,
                'data' => $alt,
                'climb' => $totalalt
            ];
            $detail['speed'] = [
                'x' => $x,
                'data' => $speed,
                'unit' => 'miles/h'
            ];
            $detail['heart'] = [
                'x' => $minutes,
                'data' => $heart,
                'unit' => 'Times/minute'
            ];

            $detail['bicycleType'] = [
                'txt' => '自行车类型',
                'data' => [
                    ['id'=>1,'name'=>'山地车'],
                    ['id'=>2,'name'=>'自行车'],
                    ['id'=>3,'name'=>'旅行车']
                ]
            ];
            $detail['ground'] = [
                'txt' => lang('Gravel'),
                'data' => [
                    ['id'=>1,'name'=>lang('Unpaved')],
                    ['id'=>2,'name'=>lang('Paved')],
                    ['id'=>3,'name'=>lang('Mountain')]
                ]
            ];
            $actuahourse = intval($detail['actualDuration'])>=10?floatval(sprintf('%.1f',intval($detail['actualDuration'])/3600)):0.00;
            $detail['overall'] = [
                //'uniform' => $detail['actualdistance']>100&&$actuahourse>0 ? floatval(sprintf('%.1f',($detail['actualdistance']/1000)/$actuahourse)).'km':floatval($detail['actualdistance']).'m',//均速
                'uniform' => $detail['actualdistance']>10&&$actuahourse>0 ? floatval(sprintf('%.1f',($detail['actualdistance']*0.00062137)/$actuahourse)).'miles':'0.0miles',//均速
                //'climb' => floatval(sprintf('%.1f',($zuialt-$zuifall)*3.28083989501)).'feet',//爬升
                'climb' => $totalalt,//爬升
                'mileage' => $detail['mileage'],//里程
                'calories' => $detail['calories'],//卡路里
                'number' => 'FA IEuu'.$detail['id'],
                //'average' => '75m',
                'entire' => floatval($totalperhour).'miles',//全程均速
                'fastest' => floatval($perhour).'miles/h',//最快时速
                'cumulativeRise' => $totalalt,//累计爬升
                'cumulativeLow' => $totalfalling,//累计下降
                'totalcalories' => $detail['calories']
            ];
            
        }
        $data = [
                    'detail'  => $detail
                ];
        $this->success('', $data);
    }
    //骑行时长转时间格式
    function changeTimeType($seconds){
        if ($seconds > 3600){
            $hours = intval($seconds/3600);
            $minutes = $seconds % 3600;
            $time = $hours.":".gmstrftime('%M:%S', $minutes);
        }else{
            $time = gmstrftime('%H:%M:%S', $seconds);
        }
        return $time;
    }

    /**
     * 删除骑行记录
     */
    public function cyclingDel()
    {
        $id = $this->request->post('id');
        $userid = $this->auth->id;
        Db::name('cycling')->where(['id'=>$id,'userid'=>$userid])->delete();
        $this->success(__('Delete the success'));
    }

    /**
     * 骑行线路搜索记录
     */
    public function searchRecord()
    {
        $userid = $this->auth->id;
        $list = Db::name('cycling_search')->where('userid',$userid)->select();
        $data = [
                    'list'  => $list
                ];
        $this->success('', $data);
    }

    /**
     * 骑行线路搜索记录添加
     */
    public function searchRecordAdd()
    {
        $userid = $this->auth->id;
        $this->fangchu();
        $data = $this->request->post();
        $data['userid'] = $userid;
        $data['createtime'] = date('Y-m-d H:i:s',time());
        $list = Db::name('cycling_search')->insert($data);
        $this->success();
    }

    /**
     * 骑行线路搜索记录清空
     */
    public function searchRecordDel()
    {
        $userid = $this->auth->id;
        $list = Db::name('cycling_search')->where('userid',$userid)->delete();
        $this->success(__('Delete the success'));
    }

    /**
     * 删除用户骑行记录
     */
    public function cyclingRecordDel()
    {
        $userid = $this->auth->id;
        Db::name('cycling')->where('userid',$userid)->delete();
        $this->success(__('Delete the success'));
    }

    /**
     * 重置里程记录
     */
    public function resetMileage()
    {
        $userid = $this->auth->id;
        Db::name('user_cycling')->where('uid',$userid)->update(['totaldistance'=>0]);
        $this->success(__('Reset the success'));
    }

    /**
     * 添加私人线路
     */
    public function addPrivate()
    {
        $userid = $this->auth->id;
        $this->fangchu();
        $params = $this->request->post();
        $id = $this->request->post('id');
        $name = $this->request->post('name');
        $cycling = Db::name('cycling')->where(['id'=>$id,'userid'=>$userid])->find();
        $private = Db::name('user_privateline')->where(['cid'=>$id,'userid'=>$userid])->find();
        if ($private) {
            $this->success(__('Add a success'));
        }
        if ($cycling&&!$private) {
            $data = [
                'userid'=>$userid,
                'cid'=>$id,
                'name'=>$name,
                'user_region'=>$cycling['user_region'],
                'startpost'=>$cycling['user_post'],
                'startlng'=>$cycling['user_lng'],
                'startlat'=>$cycling['user_lat'],
                'endlng'=>$cycling['end_lng'],
                'endlat'=>$cycling['end_lat'],
                'endpost'=>$cycling['end_post'],
                'distance'=>$cycling['distance'],
                'actualdistance'=>$cycling['actualdistance'],
                'actualDuration'=>$cycling['actualDuration'],
                'climb'=>$cycling['climb'],
                'introduce'=>$params['introduce'],
                'calories'=>$cycling['calories'],
                'bicycleType'=>$params['bicycleType'],
                'ground'=>$params['ground'],
                'lineimg'=>$cycling['lineimg'],
                'imgs'=>$params['imgs'],
                'share'=>$params['share'],
                'linestatus'=>$params['linestatus'],
                'json'=>$cycling['json'],
                'status'=>1,
                'createtime'=>date('Y-m-d H:i:s',time())
            ];
            $aid = Db::name('user_privateline')->insertGetId($data);
            $this->success(__('Add a success')); 
        }else{
           $this->error(__('')); 
        }
    }

    /**
     * 编辑私人线路
     */
    public function editorPrivate()
    {
        $userid = $this->auth->id;
        $params = $this->request->post();
        $id = $this->request->post('id');
        $name = $this->request->post('name');
        //$cycling = Db::name('cycling')->where(['id'=>$id,'userid'=>$userid])->find();
        $private = Db::name('user_privateline')->where(['id'=>$id,'userid'=>$userid])->find();
        if (!$private) {
            $this->error(__(''));
        }
        $data = [
            'name'=>$name,
            'introduce'=>$params['introduce'],
            'bicycleType'=>$params['bicycleType'],
            'ground'=>$params['ground'],
            'imgs'=>$params['imgs'],
            'share'=>$params['share'],
            'linestatus'=>$params['linestatus']
        ];
        $aid = Db::name('user_privateline')->where(['id'=>$id,'userid'=>$userid])->update($data);
        $this->success(__('Modify the success')); 
    }
    /**
     * 上传图片
     */
    public function uploadimg(){
        Config::set('default_return_type', 'json');
        //必须设定cdnurl为空,否则cdnurl函数计算错误
        Config::set('upload.cdnurl', '');
        $type = $this->request->post("type");
        $chunkid = $this->request->post("chunkid");
        if ($chunkid) {
            if (!Config::get('upload.chunking')) {
                $this->error(__('Chunk file disabled'));
            }
            $action = $this->request->post("action");
            $chunkindex = $this->request->post("chunkindex/d");
            $chunkcount = $this->request->post("chunkcount/d");
            $filename = $this->request->post("filename");
            $method = $this->request->method(true);
            if ($action == 'merge') {
                $attachment = null;
                //合并分片文件
                try {
                    $upload = new Upload();
                    $attachment = $upload->merge($chunkid, $chunkcount, $filename);
                } catch (UploadException $e) {
                    $this->error($e->getMessage());
                }
                $user = $this->auth->getUser();
                $user->avatar = $attachment->url;
                $user->save();
                $this->success('', ['fullurl' => cdnurl($attachment->url, true)]);
            } elseif ($method == 'clean') {
                //删除冗余的分片文件
                try {
                    $upload = new Upload();
                    $upload->clean($chunkid);
                } catch (UploadException $e) {
                    $this->error($e->getMessage());
                }
                $this->success();
            } else {
                //上传分片文件
                //默认普通上传文件
                $file = $this->request->file('file');
                try {
                    $upload = new Upload($file);
                    $upload->chunk($chunkid, $chunkindex, $chunkcount);
                } catch (UploadException $e) {
                    $this->error($e->getMessage());
                }
                $this->success();
            }
        } else {
            $attachment = null;
            //默认普通上传文件
            if ($type=='base64') {
                $file = $this->request->post('file');
                $attachmenturl = $this->saveBase64($file);
            }else{
                $file = $this->request->file('file');
                try {
                    $upload = new Upload($file);
                    $attachment = $upload->upload();
                    $attachmenturl = $attachment->url;
                } catch (UploadException $e) {
                    $this->error($e->getMessage());
                }
            }
            $this->success('', ['url'=>$attachmenturl,'fullurl' => cdnurl($attachmenturl, true)]);
        }
    }

    /**
     * 取消私人线路
     */
    public function cancelPrivate()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        Db::name('user_privateline')->where(['id'=>$id,'userid'=>$userid])->update(['status'=>2]);
        $this->success(__('Cancel the success'));
    }

    /**
     * 用户私人线路列表
     */
    public function userPrivateList()
    {
        $userid = $this->auth->id;
        $params = $this->request->post();
        $key = $params['key'];
        $where = [];
        if ($key) {
            $where['name|endpost'] = ['like','%'.$key.'%'];
        }
        $page = isset($params['page'])&&is_numeric($params['page']) ? $params['page'] : 1;
        $pageSize = isset($params['pageSize'])&&is_numeric($params['pageSize']) ? $params['pageSize'] : 10;
        $list = Db::name('user_privateline')
        ->where(['userid'=>$userid,'status'=>1])
        ->where($where)
        ->order('createtime desc')
        ->limit(($page - 1)*$pageSize,$pageSize)
        ->select();
        foreach ($list as &$vs) {
            switch ($vs['ground']) {
                case 1:
                    $vs['ground_text'] = lang('Unpaved');
                    break;

                case 2:
                    $vs['ground_text'] = lang('Paved');
                    break;

                case 3:
                    $vs['ground_text'] = lang('Mountain');
                    break;
                
                default:
                    $vs['ground_text'] = "";
                    break;
            }
        }
        unset($vs);
        $data = [
                    'list'  => $list
                ];
        $this->success('', $data);
    }

    /**
     * 私人线路列表
     */
    public function privateList()
    {
        $userid = $this->auth->id;
        $params = $this->request->post();
        $lat = $this->request->post('lat');
        $lng = $this->request->post('lng');
        $key = $params['key'];
        $type = $params['type'];
        $where = [];
        $ip = request()->ip();
        if (!$lat&&!$lng&&!$ip) {
            $this->error(__('Please get positioning'));
        }
        
        if ($key) {
            $where['name|endpost'] = ['like','%'.$key.'%'];
        }
        if ($lat&&$lng){
            $postplace = $this->mapboxaddress($lng.",".$lat);
            $postplace = $postplace['place'];
        }else{
            $params = [
                    'ip' => $ip,
            ];
            $result = Http::sendRequest("http://ip-api.com/json/", $params, 'GET');
            if ($result['ret']) {
                $access = (array)json_decode($result['msg'], true);
                $postplace = $access['city'];
            }
        }
        //增加筛选骑行距离0的筛出条件
        //$where['actualdistance'] = ['>',0];
        if ($type) {
            switch ($type) {
                case 'collection':
                    $ids = Db::name('user_private_colletion')->where(['userid'=>$userid,'status'=>1])->column('privateid');
                    $where['id'] = ['in',implode(',',$ids)];
                    break;
                case 'private':
                    $where['userid'] = $userid;
                    $where['linestatus'] = 1;
                    break;

                case 'my':
                    $where['userid'] = $userid;
                    //$where['linestatus'] = 1;
                    break;
                
                default:
                    if ($postplace) {
                        $where['user_region'] = ['like','%'.$postplace.'%'];
                    }
                    $where['linestatus'] = 2;
                    break;
            }
        }else{
            if ($postplace) {
                $where['user_region'] = ['like','%'.$postplace.'%'];
            }
            $where['linestatus'] = 2;
        }
        $page = isset($params['page'])&&is_numeric($params['page']) ? $params['page'] : 1;
        $pageSize = isset($params['pageSize'])&&is_numeric($params['pageSize']) ? $params['pageSize'] : 10;
        $list = Db::name('user_privateline')
        ->where(['status'=>1])
        ->where($where)
        ->order('praisenum desc,createtime desc')
        ->limit(($page - 1)*$pageSize,$pageSize)
        ->select();
        if ($page==1 && !$list) {
            if ($postplace) {
                $postplace = explode(',', $postplace);
                $where['user_region'] = ['like','%'.trim($postplace[count($postplace)-1]).'%'];
                $list = Db::name('user_privateline')
                ->where(['status'=>1])
                ->where($where)
                ->order('praisenum desc,createtime desc')
                ->limit(10)
                ->select();
            }
            
        }
        foreach ($list as &$vv) {

            switch ($vv['ground']) {
                case 1:
                    $vv['ground_text'] = lang('Unpaved');
                    break;

                case 2:
                    $vv['ground_text'] = lang('Paved');
                    break;

                case 3:
                    $vv['ground_text'] = lang('Mountain');
                    break;
                
                default:
                    $vv['ground_text'] = "";
                    break;
            }
            if ($vv['userid'] == $userid ) {
                $vv['isuser'] = 1;
            }else{
                $vv['isuser'] = 0;
            }
            $vv['ispraise'] = Db::name('user_private_praise')->where(['userid'=>$userid,'privateid'=>$vv['id']])->value('status')==1?true:false;
            $vv['iscollection'] = Db::name('user_private_colletion')->where(['userid'=>$userid,'privateid'=>$vv['id']])->value('status')==1?true:false;
            //$vv['mileage'] = $vv['actualdistance']>100 ? floatval(sprintf('%.1f',$vv['actualdistance']/1000)).'km':floatval($vv['actualdistance']).'m';
            $vv['mileage'] = $vv['actualdistance']>60 ? floatval(sprintf('%.1f',$vv['actualdistance']*0.00062137)).'miles':'0.0miles';

            $vv['num'] = floatval(sprintf('%.1f',$vv['climb']*3.28083989501)).'feet';
            $vv['climb'] = floatval(sprintf('%.1f',$vv['climb']*3.28083989501));
            $vv['calories'] = $vv['calories'].'kcal';
            $vv['timelength'] = $vv['actualDuration']>0?$this->changeTimeType($vv['actualDuration']):'00:00:00';
            if (!$vv['lineimg']) {
                $vv['lineimg'] = cdnurl('/assets/img/linedetail.jpg',true);
            }
            //$vv['lineimg'] = cdnurl($vv['lineimg'],true);
            $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
            $vv['fulllineimg'] = '';
            if(!preg_match($str, $vv['lineimg']))
            { 
                $vv['fulllineimg'] = cdnurl($vv['lineimg'],true);
            }else{
                $vv['fulllineimg'] = $vv['lineimg'];
            }
            if ($vv['imgs']) {
                $vv['imgs'] = explode(',',$vv['imgs']);
                foreach ($vv['imgs'] as &$vs) {
                    $vs = cdnurl($vs,true);
                }
                unset($vs);
            }else{
                $vv['imgs'] = [];
            }
            if (!$vv['json']||$vv['json']=='null') {
                $vv['json'] = [];
            }else{
                if (strstr($vv['json'], 'gpx') !== false) {
                    $vv['json'] = $this->parsingxml($vv['json']);
                }else{
                    $vv['json'] = json_decode($vv['json'],true);
                }
            }
        }
        unset($vv);
        $data = [
                    'list'  => $list
                ];
        $this->success('', $data);
    }

    /**
     * 私人线路详情
     */
    public function privateDetail()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        $lat = $this->request->post('lat');
        $lng = $this->request->post('lng');
        $detail = Db::name('user_privateline')
        ->where(['id'=>$id])
        ->find();
        if ($detail) {
            $ridi = json_decode(Db::name('user_riding_heartbeat')->where(['cid'=>$detail['cid']])->value('jsonlist'),true);
            if (!$detail['json']) {
                if ($ridi) {
                    $detail['json'] = $ridi;
                }else{
                    $detail['json'] = [];
                } 
            }else{
                if (strstr($detail['json'], 'gpx') !== false) {
                    $ridi = $this->parsingxml($detail['json']);
                    $detail['json'] = $ridi;
                }else{
                    $ridi = json_decode($detail['json'],true);
                    $detail['json'] = json_decode($detail['json'],true);
                }
            }
            //$detail['mileage'] = $detail['actualdistance']>100 ? floatval(sprintf('%.1f',$detail['actualdistance']/1000)).'km':floatval($detail['actualdistance']).'m';
            $detail['mileage'] = $detail['actualdistance']>60 ? floatval(sprintf('%.1f',$detail['actualdistance']*0.00062137)).'miles':'0.0miles';
            
            $detail['timelength'] = $detail['actualDuration']>0?$this->changeTimeType($detail['actualDuration']):'00:00:00';
            $detail['num'] = floatval(sprintf('%.1f',$detail['climb']*3.28083989501)).'feet';
            $detail['calories'] = $detail['calories'].'kcal';
            $detail['ispraise'] = Db::name('user_private_praise')->where(['userid'=>$userid,'privateid'=>$detail['id']])->value('status')==1?true:false;
            $detail['iscollection'] = Db::name('user_private_colletion')->where(['userid'=>$userid,'privateid'=>$detail['id']])->value('status')==1?true:false;
            if (!$detail['lineimg']) {
                $detail['lineimg'] = cdnurl('/assets/img/linedetail.jpg',true);
            }
            $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
            $detail['fulllineimg'] = '';
            if(!preg_match($str, $detail['lineimg']))
            { 
                $detail['fulllineimg'] = cdnurl($detail['lineimg'],true);
            }else{
                $detail['fulllineimg'] = $detail['lineimg'];
            }
            
            $detail['content'] = $detail['introduce'];

            switch ($detail['ground']) {
                case 1:
                    $detail['ground_text'] = lang('Unpaved');
                    break;

                case 2:
                    $detail['ground_text'] = lang('Paved');
                    break;

                case 3:
                    $detail['ground_text'] = lang('Mountain');
                    break;
                
                default:
                    $detail['ground_text'] = "";
                    break;
            }

            if ($detail['userid'] == $userid ) {
                $detail['isuser'] = 1;
            }else{
                $detail['isuser'] = 0;
            }
            //$ridi = json_decode(Db::name('user_riding_heartbeat')->where(['cid'=>$detail['cid']])->value('jsonlist'),true);
            $x = [];//x轴骑行距离组
            $alt = [];//高度组
            if ($ridi) {
                
                $n = count($ridi)>=7?intval(count($ridi)/6):1;
                $s = $n==1?count($ridi):7;
                $t = 0;
                for ($i=0; $i < $s; $i++) { 
                    if ($i==6) {
                        $t = count($ridi)-1;
                    }
                    if (isset($ridi[$t]['distance'])) {
                        //$x[$i] = $ridi[$t]['distance']>0?floatval(sprintf('%.1f',$ridi[$t]['distance']/1000)):0;
                        $x[$i] = $ridi[$t]['distance']>0?floatval(sprintf('%.1f',$ridi[$t]['distance']*0.00062137)):0;
                        
                    }
                    if (isset($ridi[$t]['totalalt'])) {
                        $alt[$i] = $ridi[$t]['totalalt']>0?floatval(sprintf('%.0f',$ridi[$t]['totalalt']*3.28083989501)):0;
                        if (isset($zuialt)&&$alt[$i]>$zuialt) {
                            $zuialt = $alt[$i];
                        }
                    }else{
                        $alt[$i] = 0;
                    }
                    $t = $t+$n;
                }
            }
            $detail['highly'] = [
                'x' => $x,
                'data' => $alt,
                'climb' => floatval(sprintf('%.1f',$detail['climb']*3.28083989501)).'feet'
            ];
            $detail['fullimgs'] = [];
            if ($detail['imgs']) {
                $detail['fullimgs'] = explode(',',$detail['imgs']);
                foreach ($detail['fullimgs'] as &$vs) {
                    $vs = cdnurl($vs,true);
                }
                unset($vs);
                $detail['imgs'] = explode(',',$detail['imgs']);
            }else{
                $detail['imgs'] = [];
            }
            $detail['commnum'] = Db::name('user_private_comments')->where(['privateid'=>$id,'recid'=>0])->count();
            $comments = Db::name('user_private_comments')->where(['privateid'=>$id,'recid'=>0])->limit(0,3)->order('createtime desc')->select();
            foreach ($comments as &$vs) {
                $vs['user'] = Db::name('user')->where('id',$vs['userid'])->field('nickname,name,avatar')->find();
                if ($vs['user']) {
                    $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
                    if(preg_match($str, $vs['user']['avatar']))
                    { 
                        $vs['user']['avatar'] = $vs['user']['avatar'];
                    }else{
                        $vs['user']['avatar'] = cdnurl($vs['user']['avatar'],true);
                    }
                    
                }
                $vs['recnum'] = Db::name('user_private_comments')->where(['recid'=>$vs['id']])->count();
                $rec = Db::name('user_private_comments')->where(['recid'=>$vs['id']])->limit(0,3)->order('createtime desc')->select();
                foreach ($rec as &$vss) {
                    $vss['user'] = Db::name('user')->where('id',$vss['userid'])->field('nickname,name,avatar')->find();
                    if ($vss['user']) {
                        $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
                        if(preg_match($str, $vs['user']['avatar']))
                        { 
                            $vs['user']['avatar'] = $vs['user']['avatar'];
                        }else{
                            $vs['user']['avatar'] = cdnurl($vs['user']['avatar'],true);
                        }
                    }
                }
                unset($vss);
                $vs['rec'] = $rec;
            }
            unset($vs);
            $detail['comments'] = $comments;
            if ($lat&&$lng) {
                $detail['isOrigin'] = $this->getDistances($lat,$lng,$detail['startlat'],$detail['startlng'])>=100?true:false;
                $detail['isStart'] = $this->getDistances($lat,$lng,$detail['startlat'],$detail['startlng'])>=100?false:true;
            }else{
                $detail['isOrigin'] = true;
                $detail['isStart'] = true;
            }
        }
        $data = [
                    'detail'  => $detail
                ];
        $this->success('', $data);
    }

    /**
     * 评论列表
     */
    public function commentslist()
    {
        $userid = $this->auth->id;
        $pid = $this->request->post('pid');
        $page = isset($params['page'])&&is_numeric($params['page']) ? $params['page'] : 1;
        $pageSize = isset($params['pageSize'])&&is_numeric($params['pageSize']) ? $params['pageSize'] : 10;
        $comments = Db::name('user_private_comments')
        ->where(['privateid'=>$pid,'recid'=>0])
        ->limit(($page - 1)*$pageSize,$pageSize)
        ->order('createtime desc')
        ->select();
        foreach ($comments as &$vs) {
            $vs['user'] = Db::name('user')->where('id',$vs['userid'])->field('nickname,name,avatar')->find();
            if ($vs['user']) {
                $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
                if(preg_match($str, $vs['user']['avatar']))
                { 
                    $vs['user']['avatar'] = $vs['user']['avatar'];
                }else{
                    $vs['user']['avatar'] = cdnurl($vs['user']['avatar'],true);
                }
            }
            
        }
        unset($vs);
        $data = [
                    'comments'  => $comments
                ];
        $this->success('', $data);
    }

    /**
     * 跟评列表
     */
    public function evaluationlist()
    {
        $userid = $this->auth->id;
        $pid = $this->request->post('pid');
        $page = isset($params['page'])&&is_numeric($params['page']) ? $params['page'] : 1;
        $pageSize = isset($params['pageSize'])&&is_numeric($params['pageSize']) ? $params['pageSize'] : 10;
        $comments = Db::name('user_private_comments')
        ->where(['recid'=>$pid])
        ->limit(($page - 1)*$pageSize,$pageSize)
        ->order('createtime desc')
        ->select();
        $rec = Db::name('user_private_comments')->where(['recid'=>$pid])->select();
        foreach ($comments as &$vs) {
            $vs['user'] = Db::name('user')->where('id',$vs['userid'])->field('nickname,name,avatar')->find();
            if ($vs['user']) {
                $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
                if(preg_match($str, $vs['user']['avatar']))
                { 
                    $vs['user']['avatar'] = $vs['user']['avatar'];
                }else{
                    $vs['user']['avatar'] = cdnurl($vs['user']['avatar'],true);
                }
            }
        }
        unset($vs);
        $data = [
                    'comments'  => $comments
                ];
        $this->success('', $data);
    }

    /**
     * 评论私人线路
     */
    public function commentsPrivateline()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        $recid = $this->request->post('recid')?$this->request->post('recid'):0;//跟评id
        $text = $this->request->post('text');
        $data = [
            'userid'=>$userid,
            'recid'=>$recid,
            'privateid'=>$id,
            'content'=>$text,
            'createtime'=>date('Y-m-d H:i:s',time())
        ];
        Db::name('user_private_comments')->insert($data);
        $this->success(__('Comment on success'));
    }

    /**
     * 删除评论私人线路
     */
    public function delPrivateline()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        $data = [
            'userid'=>$userid,
            'privateid'=>$id
        ];
        Db::name('user_private_comments')->where($data)->delete();
        $this->success(__('success'));
    }

    /**
     * 点赞私人线路
     */
    public function praisePrivateline()
    {
        $userid = $this->auth->id;
        $this->fangchu();
        $id = $this->request->post('id');
        Db::name('user_privateline')->where(['id'=>$id])->setInc('praisenum');
        Db::name('user_private_praise')->insert(['userid'=>$userid,'privateid'=>$id,'status'=>1]);
        $this->success(__('Thumb up success'));
    }

    /**
     * 取消点赞私人线路
     */
    public function cancelPraiseline()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        Db::name('user_privateline')->where(['id'=>$id])->setDec('praisenum');
        Db::name('user_private_praise')->where(['userid'=>$userid,'privateid'=>$id])->delete();
        $this->success(__('Cancel the success'));
    }

    /**
     * 收藏私人线路
     */
    public function collectionPrivateline()
    {
        $userid = $this->auth->id;
        $this->fangchu();
        $id = $this->request->post('id');
        Db::name('user_privateline')->where(['id'=>$id])->setInc('collectionnum');
        Db::name('user_private_colletion')->insert(['userid'=>$userid,'privateid'=>$id,'status'=>1]);
        $this->success(__('Collection of success'));
    }

    /**
     * 取消收藏私人线路
     */
    public function cancelCollectionline()
    {
        $userid = $this->auth->id;
        $id = $this->request->post('id');
        Db::name('user_privateline')->where(['id'=>$id])->setDec('collectionnum');
        Db::name('user_private_colletion')->where(['userid'=>$userid,'privateid'=>$id])->delete();
        $this->success(__('Cancel the success'));
    }

    /**
     * 骑行心跳轮询
     */
    public function ridingHeartbeat()
    {
        $userid = $this->auth->id;
        $user = $this->auth->getUser();
        $params = $this->request->post();
        if (!isset($params['heartbeat'])) {
            $this->error('未发送心跳数据');
        }
        $heartbeat = json_decode(html_entity_decode(htmlspecialchars_decode(stripslashes($params['heartbeat']))),true);
        if (!isset($heartbeat['lat'])) {
            $this->error('未发送坐标数据');
        }
        $hearjson = Db::name('user_riding_heartbeat')->where(['cid'=>$params['cid'],'uid'=>$userid])->value('jsonlist');
        $hearlist = [];
        //计算卡路里 代谢当量*时间（小时）*体重（公斤）*1.05（系数）
        if (!$user['weight']) {
            //未设置体重给一个默认体重
            $user['weight'] = 65;
        }
        $ctime = time()-strtotime(Db::name('cycling')->where(['id'=>$params['cid']])->value('createtime'));
        $calories = floatval(6.5*($ctime/3600)*$user['weight']*1.05);
        if (!$hearjson) {
            $cyc = Db::name('cycling')->where(['id'=>$params['cid']])->find();
            $heartbeat['distance'] = $this->getDistances($cyc['user_lat'],$cyc['user_lng'],$heartbeat['lat'],$heartbeat['lng']);
            if (isset($heartbeat['alt'])) {
               //这个是海拔高度
                
            }
            $heartbeat['currentalt'] = 0;//当前高度
            $heartbeat['totalalt'] = 0;//累计上升
            $heartbeat['totalfalling'] = 0;//累计下降
            $heartbeat['calories'] = floatval(sprintf('%.1f',$calories));
            $heartbeat['createtime'] = time();
            $heartbeat['totime'] = time()-strtotime($cyc['createtime']);
            
            $hearlist[0] = $heartbeat;
            Db::name('user_riding_heartbeat')->insert(['cid'=>$params['cid'],'uid'=>$userid,'jsonlist'=>json_encode($hearlist),'createtime'=>date('Y-m-d H:i:s',time())]);
        }else{
            $createtime = Db::name('cycling')->where(['id'=>$params['cid']])->value('createtime');
            $hearlist = json_decode($hearjson,true);
            $cyc = $hearlist[count($hearlist)-1];
            $heartbeat['distance'] = $this->getDistances($cyc['lat'],$cyc['lng'],$heartbeat['lat'],$heartbeat['lng']);
            $heartbeat['distance'] = $heartbeat['distance']+$cyc['distance'];
            if (isset($heartbeat['alt'])) {
                if (isset($heartbeat['alt'])&&intval($heartbeat['alt'])>intval($cyc['alt'])) {
                    $heartbeat['totalfalling'] = intval(sprintf('%.1f',$cyc['totalfalling']));
                    $toalt = intval($heartbeat['alt'])-intval($cyc['alt']);
                    $heartbeat['currentalt'] = $toalt;
                    //误差调整
                    if ($toalt>=1) {
                        $heartbeat['totalalt'] = floatval(sprintf('%.1f',intval($cyc['totalalt'])+$toalt));
                    }else{
                        $heartbeat['totalalt'] = floatval($cyc['totalalt']);
                    }
                    
                }else{
                    if (isset($heartbeat['currentalt'])) {
                        $heartbeat['currentalt'] = $cyc['currentalt'];
                    }
                    if (isset($cyc['totalalt'])) {
                        $heartbeat['totalalt'] = intval(sprintf('%.1f',$cyc['totalalt']));
                        $falling = intval($cyc['alt'])-intval($heartbeat['alt']);
                        if (isset($cyc['totalfalling'])) {
                            //误差调整
                            if ($falling>=1) {
                                $heartbeat['totalfalling'] = floatval(sprintf('%.1f',intval($cyc['totalfalling'])+$falling));
                            }else{
                                $heartbeat['totalfalling'] = floatval($cyc['totalfalling']);
                            }
                            
                        }else{
                            $heartbeat['totalfalling'] = 0;
                        }
                        
                    }else{
                        $heartbeat['totalalt'] = 0;
                        $heartbeat['totalfalling'] = 0;
                    }
                    
                }
               
            }
            $heartbeat['calories'] = floatval(sprintf('%.1f',$calories));
            $heartbeat['createtime'] = time();
            $heartbeat['totime'] = time()-strtotime($createtime);
            array_push($hearlist,$heartbeat);
            Db::name('user_riding_heartbeat')->where(['cid'=>$params['cid'],'uid'=>$userid])->update(['jsonlist'=>json_encode($hearlist)]);
        }
        $totalalt = isset($heartbeat['totalalt'])?$heartbeat['totalalt']:0;
        //$totalalt = $totalalt>=1000?floatval(sprintf('%.1f',$totalalt/1000)).'km':floatval(sprintf('%.1f',$totalalt)).'m';
        $totalalt = floatval(sprintf('%.1f',$totalalt*3.28083989501)).'feet';
        
        $data = [
            'distance' => $heartbeat['distance']>=170?floatval(sprintf('%.1f',$heartbeat['distance'] * 0.00062137)).'miles':'0.0miles',
            'totalalt' => $totalalt,
            'calories' => floatval(sprintf('%.1f',$calories))
        ];
        $this->success('',$data);

    }

    //测算两点之间距离 单位m
    function getDistances($lat1, $lng1, $lat2, $lng2){
        $radLat1 = $lat1 * (PI / 180);
        $radLat2 = $lat2 * (PI / 180);
 
        $a = $radLat1 - $radLat2;
        $b = ($lng1 * (PI / 180)) - ($lng2 * (PI / 180));
 
        $s = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1)*cos($radLat2)*pow(sin($b/2),2)));
        $s = $s * EARTH_RADIUS;
        $s = round($s * 10000) / 10000;
        return floatval(sprintf('%.1f',$s*1000));
    }

    /**
     * 申请试骑
     */
    public function sendTryride()
    {
        $userid = $this->auth->id;
        $this->usersendkefu($userid,lang('test ride'));
        $this->success(__(''));
    }

    /**
     * 接受试骑
     */
    public function acceptTryride()
    {
        $userid = $this->auth->id;
        $id = $this->request->param('id');
        Db::name('tryride')->where(['applyuid'=>$userid,'id'=>$id])->update(['applystatus'=>1]);
        Db::name('tryride')->where(['touid'=>$userid,'id'=>$id])->update(['tostatus'=>1]);
        $st = Db::name('tryride')->where(['id'=>$id,'applystatus'=>1,'tostatus'=>1,'status'=>0])->find();
        if ($st) {
            Db::name('tryride')->where(['id'=>$id])->update(['status'=>1,'startTime'=>date('Y-m-d H:i:s',time())]);
            Db::name('user')->where('id',$userid)->update(['tryrideStatus'=>1]);
        }
        $this->success(__('Accept success'));
    }

    /**
     * 拒绝试骑
     */
    public function refusedTryride()
    {
        $userid = $this->auth->id;
        $id = $this->request->param('id');
        $ks = Db::name('tryride')->where(['applyuid'=>$userid,'id'=>$id])->update(['applystatus'=>2,'status'=>2]);
        if ($ks) {
            $this->usersendkefu($userid,lang('Applicant Cancel',[$this->auth->nickname]));
        }
        $ts = Db::name('tryride')->where(['touid'=>$userid,'id'=>$id])->update(['tostatus'=>2,'status'=>2]);
        Db::name('user')->where('id',$userid)->update(['tryrideStatus'=>0]);
        if ($ts) {
            $this->usersendkefu($userid,lang('Respondent Cancel',[$this->auth->nickname]));
        }
        $this->success(__('Refuse to success'));
    }

    /**
     * 结束试骑
     */
    public function endTryride()
    {
        $userid = $this->auth->id;
        $id = $this->request->param('id');
        $this->fangchu();
        // Db::name('tryride')->where(['applyuid'=>$userid,'id'=>$id])->update(['applystatus'=>3,'status'=>3,'endTime'=>date('Y-m-d H:i:s')]);
        // Db::name('user')->where('id',$userid)->update(['tryrideStatus'=>0]);
        
        Db::name('tryride')->where(['applyuid'=>$userid,'id'=>$id])->update(['applystatus'=>3]);
        // Db::name('tryride')->where(['touid'=>$userid,'id'=>$id])->update(['tostatus'=>3]);
        $st = Db::name('tryride')->where(['id'=>$id,'applystatus'=>3,'status'=>1])->find();
        if ($st) {
            Db::name('tryride')->where(['id'=>$id])->update(['status'=>3,'endTime'=>date('Y-m-d H:i:s')]);
            Db::name('user')->where('id',$userid)->update(['tryrideStatus'=>0]);
            $commission = Db::name('tryride')->where(['id'=>$id])->value('commission');
            if ($commission>0) {
                Db::name('user')->where(['id'=>$st['touid']])->setInc('commission',$commission);
            }
        }
        $this->success(__('End of success'));
    }

    /**
     * 申请人试骑
     */
    public function applyTryride()
    {
        $userid = $this->auth->id;
        $status = $this->request->param('status');
        $tryride = Db::name('tryride')->where(['applyuid'=>$userid,'status'=>$status])->select();
        foreach ($tryride as &$value) {
            $endtime = strtotime($value['startTime'])+$value['time_unit'];
            $value['isend'] = $endtime>=time()?1:0;
        }
        unset($value);
        
        $data = [
            'user' => $this->auth->getUser(),
            'tryride' => $tryride,
            'num' => Db::name('tryride')->where(['applyuid'=>$userid,'status'=>3])->count(),
            'commission' => Db::name('user')->where(['id'=>$userid])->value('commission')
         ];
        $this->success('',$data);
    }

    /**
     * 被申请人试骑
     */
    public function toTryride()
    {
        $userid = $this->auth->id;
        $status = $this->request->param('status');
        $tryride = Db::name('tryride')->where(['touid'=>$userid,'status'=>$status])->select();
        foreach ($tryride as &$value) {
            $endtime = strtotime($value['startTime'])+$value['time_unit'];
            $value['isend'] = $endtime>=time()?1:0;
        }
        unset($value);
        $data = [
            'user' => $this->auth->getUser(),
            'tryride' => $tryride,
            'num' => Db::name('tryride')->where(['touid'=>$userid,'status'=>3])->count(),
            'commission' => Db::name('user')->where(['id'=>$userid])->value('commission')
         ];
        $this->success('',$data);
    }

    /**
     * 试骑展示
     */
    public function TryrideInfo()
    {
        $userid = $this->auth->id;
        $status = $this->request->param('status');
        $whereOr = ['touid'=>$userid,'status'=>$status];
        $tryride = Db::name('tryride')->where(['applyuid'=>$userid,'status'=>$status])
        ->whereNull('deletetime')
        ->whereOr(function ($query) use ($whereOr) {
            $query->where($whereOr);
        })
        ->select();
        $sq = true;
        foreach ($tryride as &$value) {
            $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
            if ($value['applyuid']==$userid) {
                $user = Db::name('user')->where(['id'=>$value['touid']])->find();
                
                if(preg_match($str, $user['avatar']))
                { 
                    $value['avatar'] =  $user['avatar'];
                }else{
                    $value['avatar'] =  cdnurl($user['avatar'],true);
                }
                $value['nickname'] = $user['nickname'];
                $value['gender'] = $user['gender']==0?lang('Woman'):lang('Man');
                $value['region'] = $user['region'];
                $value['mobile'] = $value['tomobile'];
                $value['address'] = $value['toaddress'];
                $value['cstatus'] = $value['applystatus'];
            }else{
                $sq = false;
                $user = Db::name('user')->where(['id'=>$value['applyuid']])->find();
                if(preg_match($str, $user['avatar']))
                { 
                    $value['avatar'] =  $user['avatar'];
                }else{
                    $value['avatar'] =  cdnurl($user['avatar'],true);
                }
                $value['nickname'] = $user['nickname'];
                $value['gender'] = $user['gender']==0?lang('Woman'):lang('Man');
                $value['region'] = $user['region'];
                $value['mobile'] = $value['applymobile'];
                $value['address'] = $value['applyaddress'];
                $value['cstatus'] = $value['tostatus'];
            }
            
            $endtime = strtotime($value['startTime'])+$value['time_unit'];
            $value['userendtime'] = date('Y-m-d H:i:s',$endtime);
            $value['isend'] = $endtime>time()?0:1;
        }
        unset($value);
        $commission = 0;
        if (!$sq) {
            $issqr = 2;
        }else{
            $issqr = 1;
        }
        $commission = floatval(sprintf('%.1f',Db::name('user')->where(['id'=>$userid])->value('commission')));
        $data = [
            'user' => $this->auth->getUser(),
            'tryride' => $tryride,
            'num' => Db::name('tryride')->where(['touid'=>$userid,'status'=>3])->count(),
            'commission' => $commission,
            'issqr' => $issqr
         ];
        $this->success('',$data);
    }

    /**
     * 申请人试骑评价
     */
    public function tryrideEvaluation()
    {
        $userid = $this->auth->id;
        $id = $this->request->param('id');
        $str = $this->request->param('str');
        Db::name('tryride')->where(['id'=>$id,'applyuid'=>$userid])->update(['evaluation'=>$str]);
        $this->success(__('Evaluation of success'));
    }

    /**
     * 试骑协议
     */
    public function tryrideAgreement()
    {
        //halt(lang('agreement'));
        $data = [
            'str' => Config::get(lang('agreement'))
        ];
        $this->success('',$data);
    }

    /**
     * 反向地理解析
     */
    public function locationParsing(){
        $latlng = input("latlng");
        $data = $this->mapboxaddress($latlng);
        $this->success('',$data);
    }

    //给客服发送消息 用户id，系统消息内容
    function usersendkefu($userid,$str){
        $user = Db::name('user')->where(['id'=>$userid])->field('nickname,avatar')->find();
        //创建用户
        $kefuid = Db::name('kefu_user')->where(['user_id'=>$userid])->value('id');
        if (!$kefuid) {
            $token = \fast\Random::uuid();
            $kefuid = Db::name('kefu_user')->insertGetId(['user_id'=>$userid,'avatar'=>$user['avatar'],'nickname'=>$user['nickname'],'token'=>$token,'createtime'=>time()]);
        }
        //创建会话
        $session = Db::name('kefu_session')->where(['user_id'=>$kefuid,'deletetime'=>null])->find();
        if (!$session) {
            // 客服分配
            $csr = Common::getAppropriateCsr();
            if ($csr) {
                $session = Common::distributionCsr($csr, $userid . '||user');
            } else {
                //无法分配到客服发给admin
               $session = Common::distributionCsr('1||csr', $userid . '||user');
            }
            
        }
        $note = '用户 ' . $user['nickname'] . ' 系统消息 ';
        // 记录轨迹
        $trajectory = [
            'user_id'    => $kefuid,
            'csr_id'     => $session['csr_id'],
            'log_type'   => 0,
            'note'       => $note,
            'url'        => '',
            'referrer'   => '',
            'createtime' => time(),
        ];
        Db::name('kefu_trajectory')->insert($trajectory);
        // 插入接待记录,用于数据统计
        $reception_log = [
            'csr_id'     => $session['csr_id'],
            'user_id'    => $kefuid,
            'createtime' => time(),
        ];
        Db::name('kefu_reception_log')->insert($reception_log);
        //发送给客服消息 3=系统消息
         $aa = Common::chatRecord($session['id'],$str, 0,$kefuid . '||user');
         return true;
    }

    public function crawler(){

        $crawler = Db::name('user_crawlerline')->limit(35000,5000)->select();
        $t = 0;
        foreach ($crawler as $vv) {
            $data = [];
            //$line = Db::name('user_privateline')->where(['name'=>$vv['name'],'startlng'=>$vv['startlng'],'startlat'=>$vv['startlat']])->find();
            $line = false;
            if (!$line) {
                $data['name'] = $vv['name'];
                $isdata = Db::name('user_privateline')->where(['name'=>$vv['name'],'startlng'=>$vv['startlng'],'startlat'=>$vv['startlat']])->find();
                //halt($isdata);
                if (!$isdata||isset($isdata['json'])&&$isdata['json']) {
                    //$json = [];
                    //halt(ROOT_PATH.$vv['map_path']);
                    if ($vv['map_path']) {
                        $map_path = $vv['map_path'];
                    }else{
                        $map_path = '';
                    }
                    if ($isdata) {
                        if ($map_path) {
                            if (strstr($isdata['json'], 'gpx') !== true) {
                                Db::name('user_privateline')->where('id',$isdata['id'])->update(['json'=>$map_path]);
                            }
                        }
                    }else{
                        $startplace = $this->mapboxaddress($vv['startlng'].','.$vv['startlat']);
                        $data['startpost'] = $startplace['post'];
                        $data['user_region'] = $startplace['place'];
                        $data['startlng'] = $vv['startlng'];
                        $data['startlat'] = $vv['startlat'];
                        $endplace = $this->mapboxaddress($vv['endlng'].','.$vv['endlat']);
                        $data['endpost'] = $endplace['post'];
                        $data['endlng'] = $vv['endlng'];
                        $data['endlat'] = $vv['endlat'];
                        $data['actualdistance'] = $vv['distance'];
                        $data['actualDuration'] = $vv['actualDuration'];
                        $data['bicycleType'] = 1;
                        $data['ground'] = 1;
                        $str="/http[s]?:\\/\\/[\\w.]+[\\w\\/]*[\\w.]*\\??[\\w=&\\+\\%]*/is";
                        if(preg_match($str, $vv['lineimg']))
                        { 
                            $data['lineimg'] = $vv['lineimg'];
                        }
                        $data['share'] = 1;
                        $data['linestatus'] = 2;
                        
                        // if ($vv['json']) {
                        //     $jsond = json_decode($vv['json'],true);
                        //     $js = $jsond['gpx']['trk']['trkseg']['trkpt'];
                        //     $zuialt = 0;//最高高度
                        //     $zuifall = 0;//最低高度
                        //     foreach ($js as $key=>$vs) {
                        //         $json[$key]['alt'] = $vs['ele'];
                        //         $json[$key]['lat'] = $vs['@lat'];
                        //         $json[$key]['lng'] = $vs['@lon'];
                        //         if ($key==0) {
                        //             $json[$key]['distance'] = 0; //里程
                        //             $json[$key]['totalalt'] = 0;//累计上升
                        //             $json[$key]['totalfalling'] = 0;//累计下降
                        //         }else{
                        //             $json[$key]['distance'] = floatval(sprintf('%.1f',$json[$key-1]['distance']+$this->getDistances($js[$key-1]['@lat'],$js[$key-1]['@lon'],$vs['@lat'],$vs['@lon'])));
                        //             if (isset($vs['ele'])&&intval($vs['ele'])>=intval($js[$key-1]['ele'])) {
                        //                 $zuialt = intval($vs['ele']);
                        //                 $json[$key]['totalalt'] = intval($json[$key-1]['totalalt'])+(intval($vs['ele'])-intval($js[$key-1]['ele']));
                        //                 $json[$key]['totalfalling'] = $json[$key-1]['totalfalling'];
                        //             }else{
                        //                 $zuifall = intval($vs['ele']);
                        //                 $json[$key]['totalfalling'] = intval($json[$key-1]['totalfalling'])+(intval($js[$key-1]['ele'])-intval($vs['ele']));
                        //                 $json[$key]['totalalt'] = $json[$key-1]['totalalt'];
                        //             }
                        //         }
                                
                        //     }
                        // }
                        
                        //$data['zui'] = $zuialt-$zuifall;
                        $data['json'] = $map_path;
                        $data['climb'] = intval($vv['ascent']);
                        $data['status'] = 1;
                        $data['createtime'] = date('Y-m-d H:i:s',time());
                        //halt($data);
                    
                        Db::name('user_privateline')->insert($data);
                        $t++;
                        echo $t."条"."\r\n";
                        usleep(200000); // 延迟 0.3 秒
                    }
                    
                    
                }else{
                    $t++;
                    echo $t."重复"."\r\n";
                    //usleep(100000); // 延迟 0.1 秒
                }
            }
        }
        // echo "插入".$t."条数据";
    }

    function parsingxml($mappath){
            $json = [];
            $filename = str_replace(' ','%20',cdnurl($mappath,true));
            //halt(ROOT_PATH.'/public'.$mappath);
             if (file_exists(ROOT_PATH.'/public'.$mappath)) {
                $content = file_get_contents($filename); // 读取文件内容
                if(strpos($content, '<?xml') !== false){
                    $jsond = json_decode(json_encode(simplexml_load_string($content)),true);
                    //$js = $jsond;
                    if (isset($jsond['trk']['trkseg']['trkpt'])) {
                        $js = $jsond['trk']['trkseg']['trkpt'];
                    }else{
                        $js = [];
                    }
                    
                    //halt($js);
                    $zuialt = 0;//最高高度
                    $zuifall = 0;//最低高度
                    foreach ($js as $key=>$vs) {
                        if (isset($vs['ele'])){
                            $json[$key]['alt'] = $vs['ele'];
                        }else{
                            $json[$key]['alt'] = 0;
                        }
                        
                        $json[$key]['lat'] = $vs['@attributes']['lat'];
                        $json[$key]['lng'] = $vs['@attributes']['lon'];
                        if ($key==0) {
                            $json[$key]['distance'] = 0; //里程
                            $json[$key]['totalalt'] = 0;//累计上升
                            $json[$key]['totalfalling'] = 0;//累计下降
                        }else{
                            $json[$key]['distance'] = floatval(sprintf('%.1f',$json[$key-1]['distance']+$this->getDistances($js[$key-1]['@attributes']['lat'],$js[$key-1]['@attributes']['lon'],$vs['@attributes']['lat'],$vs['@attributes']['lon'])));
                            if (isset($vs['ele'])&&isset($js[$key-1]['ele'])&&intval($vs['ele'])>=intval($js[$key-1]['ele'])) {
                                $zuialt = intval($vs['ele']);
                                $json[$key]['totalalt'] = intval($json[$key-1]['totalalt'])+(intval($vs['ele'])-intval($js[$key-1]['ele']));
                                $json[$key]['totalfalling'] = $json[$key-1]['totalfalling'];
                            }else{
                                if (isset($vs['ele'])&&isset($js[$key-1]['ele'])){
                                    $zuifall = intval($vs['ele']);
                                    $json[$key]['totalfalling'] = intval($json[$key-1]['totalfalling'])+(intval($js[$key-1]['ele'])-intval($vs['ele']));
                                    $json[$key]['totalalt'] = $json[$key-1]['totalalt'];
                                }else{
                                    $json[$key]['totalalt'] = $json[$key-1]['totalalt'];
                                    $json[$key]['totalfalling'] = $json[$key-1]['totalfalling'];
                                }
                            }
                        }
                        
                    }
                }
            }
            return $json;
    }

    function fangchu(){
        session_start();
        if (isset($_SESSION['last_submit_time'])) {
          $lastSubmitTime = $_SESSION['last_submit_time'];
          $currentTime = time();
          
          // 如果距离上一次提交时间少于 5 秒，则禁止用户提交
          if ($currentTime - $lastSubmitTime < 5) {
            $this->error(__('Operating too fast'));
            exit();
          }
        }

        // 执行提交操作
        // ...

        // 记录当前提交时间
        $_SESSION['last_submit_time'] = time();


    }
    public function test(){
        

        $params = [
                'fields' => 'id,name,email,picture',
                'access_token' => 'EAAMrruW4YR0BAAF03QyvxehkfrNDKm55BWSXrlgV4o8ZAoCZBwlXgCep4lnAGVbnEdeAD1MIWM6eu4hUILu0zwZBZCpoVUyOc4FWS86eLDXrLGRxnJnC6stJvZAcDM1l9EJ5lQBYaZBdezZB10QFB6y6PvfZCFkOlEICNtym40vLlxrcpNRlZBpfZCrT0dkb1RAiNzy3Le7ZAOubu77pWWeYTYKci2BNv4kOMjGzYMl7eryPxbBXdnUCHiAvjmpSBMIYbAy9S3ymWR3XgZDZD'
        ];
        $result = Http::sendRequest("https://graph.facebook.com/me", $params, 'GET');
        halt($result);
        // $id = $this->request->param('id');
        // $crawler = Db::name('user_crawlerline')->where(['id'=>$id])->find();
        // $crawler['distance'] = $crawler['distance']>=100?floatval(sprintf('%.1f',$crawler['distance']/1000)).'km':floatval($crawler['distance']).'m';
        // $crawler['ascent'] = $crawler['distance']>=1000?floatval(sprintf('%.1f',$crawler['ascent']/1000)).'km':floatval($crawler['ascent']).'m';
        // $crawler['descent'] = $crawler['distance']>=1000?floatval(sprintf('%.1f',$crawler['ascent']/1000)).'km':floatval($crawler['descent']).'m';
        // $data = [
        //     'crawler'=>$crawler
        // ];
        // $token = 'pk.eyJ1IjoibGFuZ2RvbmdsZWkiLCJhIjoiY2xmOWRvcjg1MmV2bDNybGh3dWs5eDNhaCJ9.ILQRw5E7y-vRdykulCTe6w';
        // $result = Http::sendRequest("https://api.mapbox.com/geocoding/v5/mapbox.places/-73.989,40.733.json?types=country,region,place,address&access_token=".$token, [], 'GET');
        // $data = $this->gaodeaddress('121.477734,31.2579844');
        // halt($data);
        // $result = Http::sendRequest("https://restapi.amap.com/v3/geocode/regeo?output=json&location=121.477734,31.2579844&key=5e0d711dc520a746549847425fc5465f&radius=1000&extensions=base&batch=false", [], 'GET');
        // $da = (array)json_decode($result['msg'], true);
        // halt($da);
        // halt($da['features'][0]['place_name']);
        // $userid = $this->auth->id;
        // $this->usersendkefu($userid,'测试给发消息');
        // Tryride::endtoTryride();
        $this->success(__(''));
    }

}
